home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / pcroct89.arc / SEARCH.ARC / SEARCH.BAS < prev    next >
BASIC Source File  |  1990-03-21  |  12KB  |  510 lines

  1. ' $INCLUDE: 'QB.BI'
  2. DEFINT A-Z
  3.  
  4. TYPE FoundType
  5.     FileName  AS STRING * 72
  6.     count     AS INTEGER
  7. END TYPE
  8.  
  9. TYPE DTAType
  10.     reserved  AS STRING * 21
  11.     attrib    AS STRING * 1
  12.     WriteTime AS INTEGER
  13.     WriteDate AS INTEGER
  14.     Size      AS LONG
  15.     FileName  AS STRING * 13
  16. END TYPE
  17.  
  18. CONST FALSE = 0
  19. CONST TRUE = NOT FALSE
  20. CONST MaxExcl = 10
  21. CONST Normal = 0
  22. CONST Subdirectory = &H10
  23.  
  24. DECLARE SUB GetParms ()
  25. DECLARE FUNCTION Prompt$ (Text$)
  26. DECLARE SUB AddExclude (Ext$)
  27. DECLARE SUB DelExclude (Ext$)
  28. DECLARE FUNCTION Excluded% (Ext$)
  29. DECLARE SUB FindFiles ()
  30. DECLARE FUNCTION GetCurrentDir$ ()
  31. DECLARE FUNCTION DOSFindFirst% (Spec$, attrib%)
  32. DECLARE FUNCTION DOSFindNext% ()
  33. DECLARE SUB SetDTA (DTA AS DTAType)
  34. DECLARE SUB SearchFile (DTA AS DTAType)
  35. DECLARE SUB Display (FileNum%, DisplayPosn&, FileLen&)
  36. DECLARE SUB NicePrint (Text$)
  37. DECLARE FUNCTION Strip8$ (Text$)
  38. DECLARE SUB Finish ()
  39.  
  40. OPTION BASE 1
  41. DIM SHARED FileSpec$, SearchText$, OutFile$
  42. DIM SHARED Excl$(MaxExcl), ExclCount
  43. DIM SHARED CurrDir$, OrigDir$
  44. DIM SHARED Root, Subdirs, Bit8, Pause, FileOut, IgnoreCase, StatsOnly
  45. DIM SHARED Matches(200) AS FoundType, MatchCount
  46. DIM SHARED FilesSearched, MatchEntry
  47. DIM SHARED InRegs AS RegType, OutRegs AS RegType
  48. DIM SHARED InRegsX AS RegTypeX, OutRegsX AS RegTypeX
  49.  
  50. '   Set default options
  51. Root = FALSE
  52. Subdirs = FALSE
  53. Bit8 = FALSE
  54. IgnoreCase = TRUE
  55. ExclCount = 0
  56. Pause = TRUE
  57. FileOut = FALSE
  58. MatchCount = 0
  59. StatsOnly = FALSE
  60.  
  61. '**********************
  62. ' Program starts here
  63. '**********************
  64.  
  65. OrigDir$ = GetCurrentDir$
  66. GetParms
  67. IF IgnoreCase THEN
  68.     SearchText$ = UCASE$(SearchText$)
  69. END IF
  70. IF FileOut THEN
  71.     OPEN OutFile$ FOR OUTPUT AS #1
  72. ELSE
  73.     OPEN "SCRN:" FOR OUTPUT AS #1
  74. END IF
  75. IF Root THEN
  76.     CHDIR "\"
  77. END IF
  78. FindFiles
  79. Finish
  80. END
  81.  
  82. '**********************
  83. '  Get information from
  84. '  the user
  85. '**********************
  86. SUB GetParms
  87.     CLS
  88.     PRINT "Enter file(s) to search.  You may use standard DOS wildcards."
  89.     LINE INPUT "==> ", FileSpec$
  90.     IF LEN(FileSpec$) = 0 THEN END
  91.     IF INSTR(FileSpec$, ".") = 0 THEN
  92.         FileSpec$ = FileSpec$ + ".*"
  93.     END IF
  94.     PRINT
  95.     LINE INPUT "Enter text you want to find ==> ", SearchText$
  96.     IF LEN(SearchText$) = 0 THEN END
  97.  
  98.     CLS
  99.     LOCATE 2, 1
  100.     PRINT "Output file: "
  101.     PRINT "Excluded files: "
  102.     LOCATE 5, 1
  103.     PRINT "Enter number of option you want to change."
  104.     PRINT "Press <RETURN> when you are done or <ESC> to end program"
  105.     PRINT
  106.     PRINT
  107.     PRINT "       1. Include subdirectories in the search"
  108.     PRINT "       2. Start search in root directory"
  109.     PRINT "       3. Strip word processor control bits"
  110.     PRINT "       4. Ignore case while searching"
  111.     PRINT "       5. Exclude .EXE and .COM files from the search"
  112.     PRINT "       6. Exclude other files from the search"
  113.     PRINT "       7. Pause to display each match found"
  114.     PRINT "       8. Report names of files with matches only"
  115.     PRINT "       9. Send output to a file"
  116.     DO
  117.         LOCATE 9, 3
  118.         IF Subdirs THEN PRINT "++";  ELSE PRINT "  ";
  119.         LOCATE 10, 3
  120.         IF Root THEN PRINT "++";  ELSE PRINT "  ";
  121.         LOCATE 11, 3
  122.         IF Bit8 THEN PRINT "++";  ELSE PRINT "  ";
  123.         LOCATE 12, 3
  124.         IF IgnoreCase THEN PRINT "++";  ELSE PRINT "  ";
  125.         LOCATE 13, 3
  126.         IF Excluded("EXE") AND Excluded("COM") THEN PRINT "++";  ELSE PRINT "  ";
  127.         LOCATE 15, 3
  128.         IF Pause THEN PRINT "++";  ELSE PRINT "  ";
  129.         LOCATE 16, 3
  130.         IF StatsOnly THEN PRINT "++";  ELSE PRINT "  ";
  131.         LOCATE 17, 3
  132.         IF FileOut THEN PRINT "++";  ELSE PRINT "  ";
  133.         LOCATE 2, 14
  134.         PRINT STRING$(65, " ");
  135.         LOCATE 2, 14
  136.         PRINT OutFile$
  137.         LOCATE 3, 17
  138.         PRINT STRING$(MaxExcl * 6, " ");
  139.         LOCATE 3, 17
  140.         FOR Lp = 1 TO ExclCount
  141.             PRINT "*."; Excl$(Lp); " ";
  142.         NEXT Lp
  143.         LOCATE 17, 1
  144.         DO
  145.             Char$ = INPUT$(1)
  146.         LOOP UNTIL INSTR(CHR$(13) + CHR$(27) + "123456789", Char$)
  147.         SELECT CASE Char$
  148.             CASE "1"
  149.                 Subdirs = Subdirs XOR TRUE
  150.             CASE "2"
  151.                 Root = Root XOR TRUE
  152.                 IF Root THEN
  153.                     Subdirs = TRUE
  154.                 END IF
  155.             CASE "3"
  156.                 Bit8 = Bit8 XOR TRUE
  157.             CASE "4"
  158.                 IgnoreCase = IgnoreCase XOR TRUE
  159.             CASE "5"
  160.                 IF Excluded("EXE") THEN
  161.                     DelExclude ("EXE")
  162.                     DelExclude ("COM")
  163.                 ELSE
  164.                     IF ExclCount + 2 <= MaxExcl THEN
  165.                         AddExclude ("EXE")
  166.                         AddExclude ("COM")
  167.                     ELSE
  168.                         Temp$ = Prompt$("Excluded file list is full")
  169.                     END IF
  170.                 END IF
  171.             CASE "6"
  172.                 FileExt$ = Prompt$("Enter file extension to add or remove from the list")
  173.                 FileExt$ = LTRIM$(RTRIM$(UCASE$(FileExt$)))
  174.                 WHILE INSTR(FileExt$, ".")
  175.                     FileExt$ = MID$(FileExt$, INSTR(FileExt$, ".") + 1)
  176.                 WEND
  177.                 IF LEN(FileExt$) > 0 AND LEN(FileExt$) <= 3 THEN
  178.                     IF Excluded(FileExt$) THEN
  179.                         DelExclude (FileExt$)
  180.                     ELSE
  181.                         IF ExclCount < MaxExcl THEN
  182.                             AddExclude (FileExt$)
  183.                         ELSE
  184.                             FileExt$ = Prompt$("Excluded file list is full")
  185.                         END IF
  186.                     END IF
  187.                 END IF
  188.             CASE "7"
  189.                 Pause = Pause XOR TRUE
  190.             CASE "8"
  191.                 StatsOnly = StatsOnly XOR TRUE
  192.             CASE "9"
  193.                 FileOut = FileOut XOR TRUE
  194.                 IF FileOut THEN
  195.                     OutFile$ = LTRIM$(RTRIM$(UCASE$(Prompt$("Name for output file"))))
  196.                     IF LEN(OutFile$) = 0 THEN
  197.                         FileOut = FALSE
  198.                     ELSE
  199.                         Pause = FALSE
  200.                     END IF
  201.                 ELSE
  202.                     OutFile$ = ""
  203.                 END IF
  204.             CASE CHR$(27)
  205.                 END
  206.             CASE ELSE
  207.         END SELECT
  208.     LOOP UNTIL Char$ = CHR$(13)
  209. END SUB
  210.  
  211. FUNCTION Prompt$ (Text$)
  212.     OrigLine = CSRLIN
  213.     OrigPosn = POS(0)
  214.     LOCATE 23, 1
  215.     PRINT Text$;
  216.     LINE INPUT " ==> ", Temp$
  217.     LOCATE 23, 1
  218.     FOR Lp = 1 TO LEN(Text$) + LEN(Temp$) + 5
  219.         PRINT " ";
  220.     NEXT Lp
  221.     LOCATE OrigLine, OrigPosn
  222.     Prompt$ = Temp$
  223. END FUNCTION
  224.  
  225. '**********************
  226. '  Maintain list of
  227. '  excluded files
  228. '**********************
  229. SUB AddExclude (Ext$)
  230.     IF Excluded(Ext$) = FALSE AND ExclCount < MaxExcl THEN
  231.         ExclCount = ExclCount + 1
  232.         Excl$(ExclCount) = Ext$
  233.     END IF
  234. END SUB
  235.  
  236. SUB DelExclude (Ext$)
  237.     Found = FALSE
  238.     FOR Lp = 1 TO ExclCount
  239.         IF Excl$(Lp) = Ext$ THEN
  240.             Found = TRUE
  241.             FOR lp2 = Lp TO ExclCount - 1
  242.                 Excl$(lp2) = Excl$(lp2 + 1)
  243.             NEXT lp2
  244.         END IF
  245.     NEXT Lp
  246.     IF Found THEN
  247.         ExclCount = ExclCount - 1
  248.     END IF
  249. END SUB
  250.  
  251. FUNCTION Excluded (Ext$)
  252.     FOR Lp = 1 TO ExclCount
  253.         IF Excl$(Lp) = Ext$ THEN
  254.             Excluded = TRUE
  255.             EXIT FUNCTION
  256.         END IF
  257.     NEXT Lp
  258.     Excluded = FALSE
  259. END FUNCTION
  260.  
  261. '**********************
  262. '  Find files to seach
  263. '**********************
  264. SUB FindFiles
  265.     DIM LocalDTA AS DTAType
  266.     CALL SetDTA(LocalDTA)
  267.     CurrentDIR$ = GetCurrentDir$
  268.     IF DOSFindFirst(FileSpec$, Normal) THEN
  269.         DO
  270.             CALL SearchFile(LocalDTA)
  271.         LOOP WHILE DOSFindNext
  272.     END IF
  273.     IF Subdirs THEN
  274.         IF DOSFindFirst("*.*", Subdirectory) THEN
  275.             DO
  276.                 IF LocalDTA.attrib$ = CHR$(Subdirectory) AND LEFT$(LocalDTA.FileName$, 1) <> "." THEN
  277.                     CHDIR (LocalDTA.FileName$)
  278.                     FindFiles
  279.                     CALL SetDTA(LocalDTA)
  280.                     CHDIR (CurrentDIR$)
  281.                 END IF
  282.             LOOP WHILE DOSFindNext
  283.         END IF
  284.     END IF
  285. END SUB
  286.  
  287. '**********************
  288. '  DOS Support functions
  289. '**********************
  290. FUNCTION GetCurrentDir$
  291.     InRegs.ax = &H1900
  292.     CALL INTERRUPT(&H21, InRegs, OutRegs)
  293.     Drive$ = CHR$((OutRegs.ax AND 255) + ASC("A")) + ":\"
  294.     TempDir$ = STRING$(64, " ")
  295.     InRegsX.ax = &H4700
  296.     InRegsX.dx = 0
  297.     InRegsX.ds = VARSEG(TempDir$)
  298.     InRegsX.si = SADD(TempDir$)
  299.     CALL interruptx(&H21, InRegsX, OutRegsX)
  300.     TempDir$ = LEFT$(TempDir$, INSTR(TempDir$, CHR$(0)) - 1)
  301.     GetCurrentDir$ = Drive$ + TempDir$
  302. END FUNCTION
  303.  
  304. FUNCTION DOSFindFirst (Spec$, attrib%)
  305.     Temp$ = Spec$ + CHR$(0)
  306.     InRegsX.ax = &H4E00
  307.     InRegsX.cx = attrib%
  308.     InRegsX.ds = VARSEG(Temp$)
  309.     InRegsX.dx = SADD(Temp$)
  310.     CALL interruptx(&H21, InRegsX, OutRegsX)
  311.     DOSFindFirst = ((OutRegsX.flags AND &H1) = 0)
  312. END FUNCTION
  313.  
  314. FUNCTION DOSFindNext
  315.     InRegs.ax = &H4F00
  316.     CALL INTERRUPT(&H21, InRegs, OutRegs)
  317.     DOSFindNext = ((OutRegs.flags AND &H1) = 0)
  318. END FUNCTION
  319.  
  320. SUB SetDTA (DTA AS DTAType)
  321.     InRegsX.ax = &H1A00
  322.     InRegsX.ds = VARSEG(DTA)
  323.     InRegsX.dx = VARPTR(DTA)
  324.     CALL interruptx(&H21, InRegsX, OutRegsX)
  325. END SUB
  326.  
  327. '**********************
  328. ' Search a file for text
  329. ' These routines make no
  330. ' assumptions about the 
  331. ' file format
  332. '**********************
  333. SUB SearchFile (DTA AS DTAType)
  334.     CONST BufLen = 8192
  335.     MatchFlag = 0
  336.     Posn = INSTR(DTA.FileName$, CHR$(0))
  337.     IF Posn THEN
  338.         File$ = LEFT$(DTA.FileName$, Posn - 1)
  339.     ELSE
  340.         File$ = DTA.FileName$
  341.     END IF
  342.     FOR Lp = 1 TO ExclCount
  343.         IF INSTR(File$, "." + Excl$(Lp)) THEN
  344.             EXIT SUB
  345.         END IF
  346.     NEXT Lp
  347.     IF NOT FileOut THEN 
  348.         CLS
  349.         PRINT #1, "Searching "; GetCurrentDir$ + "\" + File$
  350.     ELSEIF NOT StatsOnly THEN
  351.         PRINT #1, "Searching "; GetCurrentDir$ + "\" + File$
  352.     END IF
  353.     FileNum = FREEFILE
  354.     OPEN File$ FOR BINARY AS FileNum
  355.     FilesSearched = FilesSearched + 1
  356.     FileLen& = DTA.Size
  357.     FilePosn& = 1
  358.     KeepLen = LEN(SearchText$) - 1
  359.     FileBuf$ = STRING$(BufLen, 0)
  360.     MatchFlag = FALSE
  361.     DO WHILE FilePosn& < FileLen&
  362.         SEEK FileNum, FilePosn&
  363.         GET FileNum, , FileBuf$
  364.         IF Bit8 THEN
  365.             FileBuf$ = Strip8$(FileBuf$)
  366.         END IF
  367.         IF IgnoreCase THEN
  368.             FileBuf$ = UCASE$(FileBuf$)
  369.         END IF
  370.         Posn = INSTR(FileBuf$, SearchText$)
  371.         IF Posn THEN
  372.             IF MatchFlag THEN
  373.                 Matches(MatchCount).count = Matches(MatchCount).count + 1
  374.             ELSE
  375.                 MatchFlag = TRUE
  376.                 MatchCount = MatchCount + 1
  377.                 Temp$ = GetCurrentDir$ + "\" + File$
  378.                 Matches(MatchCount).FileName = Temp$
  379.                 Matches(MatchCount).count = 1
  380.             END IF
  381.             MatchEntry = MatchEntry + 1
  382.             IF NOT (FileOut AND StatsOnly) THEN 
  383.                 IF NOT (FileOut OR StatsOnly) THEN CLS
  384.                 PRINT #1, "In "; File$; " at byte"; FilePosn& + Posn - 1
  385.                 IF NOT (FileOut OR StatsOnly) THEN
  386.                     CALL Display(FileNum, FilePosn& + Posn - 1, FileLen&)
  387.                     IF Pause THEN
  388.                         COLOR 0, 7
  389.                         PRINT , "(C)ontinue, (N)ext File, (E)nd ==> ";
  390.                         DO
  391.                             Char$ = UCASE$(INPUT$(1))
  392.                         LOOP UNTIL INSTR("CNE", Char$)
  393.                         COLOR 7, 0
  394.                         IF Char$ = "E" THEN
  395.                             Finish
  396.                         ELSEIF Char$ = "N" THEN
  397.                             CLOSE FileNum
  398.                             EXIT SUB
  399.                         END IF
  400.                     END IF
  401.                 END IF
  402.             END IF
  403.             FilePosn& = FilePosn& + Posn + KeepLen
  404.         ELSE
  405.             FilePosn& = FilePosn& + BufLen - KeepLen
  406.         END IF
  407.     LOOP
  408.     CLOSE FileNum
  409. END SUB
  410.  
  411. SUB Display (FileNum, DisplayPosn&, FileLen&)
  412.     Prefix& = DisplayPosn& - 1
  413.     IF Prefix& > 200 THEN Prefix& = 200
  414.     IF Prefix& THEN
  415.         Disp$ = STRING$(Prefix&, 32)
  416.         StartPosn& = DisplayPosn& - Prefix&
  417.         SEEK FileNum, StartPosn&
  418.         GET FileNum, , Disp$
  419.         IF Bit8 THEN
  420.             Disp$ = Strip8$(Disp$)
  421.         END IF
  422.         NicePrint Disp$
  423.     ELSE
  424.         SEEK FileNum, 1
  425.     END IF
  426.     
  427.     COLOR 0, 7
  428.     Disp$ = SearchText$
  429.     GET FileNum, , Disp$
  430.     IF Bit8 THEN
  431.         Disp$ = Strip8$(Disp$)
  432.     END IF
  433.     NicePrint Disp$
  434.     COLOR 7, 0
  435.  
  436.     Suffix& = FileLen& - SEEK(FileNum) + 1
  437.     IF Suffix& > 200 THEN Suffix& = 200
  438.     IF Suffix& THEN
  439.         Disp$ = STRING$(Suffix&, 32)
  440.         GET FileNum, , Disp$
  441.         IF Bit8 THEN
  442.             Disp$ = Strip8$(Disp$)
  443.         END IF
  444.         NicePrint Disp$
  445.     END IF
  446.     NicePrint CHR$(13)
  447. END SUB
  448.  
  449. SUB NicePrint (Text$)
  450.     PrntPosn = 1
  451.     DO
  452.         Char$ = MID$(Text$, PrntPosn, 1)
  453.         IF Char$ >= " " OR Char$ = CHR$(9) THEN
  454.             PRINT #1, Char$;
  455.             PrntPosn = PrntPosn + 1
  456.         ELSEIF Char$ = CHR$(13) OR Char$ = CHR$(10) THEN
  457.             PRINT #1,
  458.             PrntPosn = PrntPosn + 1
  459.             DO WHILE MID$(Text$, PrntPosn, 1) = CHR$(13) OR MID$(Text$, PrntPosn, 1) = CHR$(10)
  460.                 PrntPosn = PrntPosn + 1
  461.             LOOP
  462.         ELSE
  463.             PRINT #1, ".";
  464.             PrntPosn = PrntPosn + 1
  465.         END IF
  466.     LOOP UNTIL PrntPosn > LEN(Text$)
  467. END SUB
  468.  
  469. FUNCTION Strip8$ (Text$)
  470.     FOR Lp = 128 TO 255
  471.         Char$ = CHR$(Lp)
  472.         StrippedChar$ = CHR$(Lp AND 127)
  473.         Posn = 1
  474.         Ptr = INSTR(Posn, Text$, Char$)
  475.         DO WHILE Ptr
  476.             MID$(Text$, Ptr, 1) = StrippedChar$
  477.             Posn = Posn + Ptr
  478.             Ptr = INSTR(Posn, Text$, Char$)
  479.         LOOP
  480.     NEXT Lp
  481.     Strip8$ = Text$
  482. END FUNCTION
  483.  
  484. '**********************
  485. ' Report final statistics
  486. '**********************
  487. SUB Finish
  488.     IF NOT FileOut AND NOT StatsOnly THEN 
  489.         CLS
  490.     ELSE
  491.         PRINT #1,
  492.     END IF
  493.     PRINT #1, SearchText$; " found in"; MatchCount; "of"; FilesSearched; "files"
  494.     PRINT #1,
  495.     IF MatchCount > 0 THEN
  496.         PRINT #1, "Count  File Name"
  497.         PRINT #1, "=====  ========="
  498.         FOR Lp = 1 TO MatchCount
  499.             PRINT #1, USING "#####  "; Matches(Lp).count;
  500.             PRINT #1, Matches(Lp).FileName
  501.         NEXT Lp
  502.     END IF
  503.     CLOSE
  504.     IF Root THEN
  505.         CHDIR OrigDir$
  506.     END IF
  507.     END
  508. END SUB
  509.  
  510.